package com.eptok.yspay.opensdkjava.util;

import org.apache.tomcat.util.codec.binary.Base64;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.Signature;
import java.util.*;

public class GenerateSignUtil {

	private final static String ALGORITHM = "SHA1WithRSA";
	private final static String CHAR_SET = "UTF-8";


	//================加签==================/
	/**
	 * 生成签名字符�?
	 * @param params
	 * @param privateKeyFile
	 * @param privateKeyPassword
	 * @return
	 * @throws Exception
	 */
	public static String generateSign(Map<String, String> params, File privateKeyFile, String privateKeyPassword) throws Exception{
		String signContent = getSignContent(params);
		String mysign = rsaSign(signContent, CHAR_SET , privateKeyFile, privateKeyPassword);
		return mysign;
	}

	/**
	 * 签名
	 */
	private static String rsaSign(String content, String charset, File privateKeyFile, String privateKeyPassword) throws Exception {
		try {
			InputStream pfxCertFileInputStream = new FileInputStream(privateKeyFile);

			System.out.println("进入签名方法：content[" + content + "], charset[" + charset + "]");
			PrivateKey priKey = getPrivateKeyFromPKCS12(privateKeyPassword, pfxCertFileInputStream);
			Signature signature = Signature.getInstance(ALGORITHM);
			signature.initSign(priKey);
			if (StringUtil.isEmpty(charset)) {
				signature.update(content.getBytes());
			} else {
				signature.update(content.getBytes(charset));
			}
			byte[] signed = signature.sign();
			String sign = new String(Base64.encodeBase64(signed), charset);
			System.out.println("进入签名完：content[" + content + "], charset[" + charset + "], sign[" + sign + "]");
			return sign;
		} catch (Exception e) {
			throw new Exception("支付报文加签异常 RSAcontent = " + content + "; charset = " + charset, e);
		}
	}

	/**
	 * 遍历以及根据重新排序
	 *
	 * @param sortedParams
	 * @return
	 */
	private static String getSignContent(Map<String, String> sortedParams) {
		StringBuffer content = new StringBuffer();
		List<String> keys = new ArrayList<String>(sortedParams.keySet());
		Collections.sort(keys);
		int index = 0;
		for (int i = 0; i < keys.size(); i++) {
			String key = keys.get(i);
			String value = sortedParams.get(key);
			if (StringUtil.areNotEmpty(key, value)) {
				content.append((index == 0 ? "" : "&") + key + "=" + value);
				index++;
			}
		}
		return content.toString();
	}

	/**
	 * 读取PKCS12格式的key（私钥）pfx格式
	 *
	 * @param password
	 * @param ins
	 * @return
	 * @throws Exception
	 * @see
	 */
	private static PrivateKey getPrivateKeyFromPKCS12(String password, InputStream ins) throws Exception {
		 Map<String, Object> certMap = new java.util.concurrent.ConcurrentHashMap<String, Object>();
		PrivateKey priKey = (PrivateKey) certMap.get("PrivateKey");
		if (priKey != null) {
			return priKey;
		}

		KeyStore keystoreCA = KeyStore.getInstance("PKCS12");
		try {
			// 读取CA根证�?
			keystoreCA.load(ins, password.toCharArray());

			Enumeration<?> aliases = keystoreCA.aliases();
			String keyAlias = null;
			if (aliases != null) {
				while (aliases.hasMoreElements()) {
					keyAlias = (String) aliases.nextElement();
					// 获取CA私钥
					priKey = (PrivateKey) (keystoreCA.getKey(keyAlias, password.toCharArray()));
					if (priKey != null) {
						certMap.put("PrivateKey", priKey);
						break;
					}
				}
			}
		} catch (Exception e) {
			if (ins != null) {
				ins.close();
			}
			throw e;
		} finally {
			if (ins != null) {
				ins.close();
			}
		}
		return priKey;
	}

	/**
	 * 生成国密签名
	 *
	 * @param param              加密的参数
	 * @param privateKeyPath     国密密钥绝对路径
	 * @param privateKeyPassword 国密密钥密码
	 * @return
	 * @throws Exception
	 */
	public static String generateGmSign(Map<String, String> param, String privateKeyPath, String privateKeyPassword) throws Exception {
		String signContent = getSignContent(param);
		return GMSignUtils.signMsgSM2(privateKeyPath,privateKeyPassword,signContent);
	}
}
